use Tk;
use Tk::Menubutton;
use Tk::After;
use lib::Cfg;

use Win32::SerialPort;
use Win32::Event;

my $cfg = lib::Cfg->new();
my $mutex = Win32::Event->new(1,0,'SEMAPHORE');

my $main = MainWindow->new;
my $transport_queue;

$main->title("Quadpod Controller");
$main->resizable(600,300);

my $interrupt;

undef($transport_queue);

my $menubar = $main->Frame(-relief=>'raised', -borderwidth=>'2')->pack(-side=>'top', -fill=>'x');
	my $mb_0 = $menubar->Menubutton( -text=>'File', -tearoff=>'0')->pack(-side=>'left');
		my $cm_0 = $mb_0->command(-label=>'Exit', -command=> sub{ $PortObj->close(); $main->after(100, sub{ $main->destroy();});});

$main->Photo('side', -file=>'../res/side.gif');
$main->Photo('top', -file=>'../res/top.gif');

my $panel = $main->Frame(-relief=>'flat', -borderwidth=>'16')->pack(-side=>'top', -fill=>'both');
	my $panel_1 = $panel->Frame(-relief=>'flat', -borderwidth=>'4')->pack(-side=>'left', -fill=>'y');

		$panel_1->Button(-text=>"Hoch", -padx=>'6', -pady=>'6', -borderwidth=>'12', -command=>sub{&handler('UP');})->pack(-side=>'top');
		$panel_1->Label(-borderwidth=>'1', -image=>'side')->pack(-side=>'top');
		$panel_1->Button(-text=>"Runter", -padx=>'6', -pady=>'6', -borderwidth=>'12', -command=>sub{&handler('DOWN');})->pack(-side=>'top');
		$panel_1->Label(-text=>'', -borderwidth=>'14')->pack(-side=>'top', -fill=>'x');
		my $panel_1_1 = $panel_1->Frame(-relief=>'flat', -borderwidth=>'4')->pack(-side=>'top', -fill=>'y');
		$panel_1_1->Button(-text=>"Schneller", -padx=>'6', -pady=>'6', -borderwidth=>'12', -command=>sub{&handler('FAST');})->pack(-side=>'left');
		$panel_1_1->Label(-text=>'   ', -borderwidth=>'4')->pack(-side=>'left', -fill=>'y');
		$panel_1_1->Button(-text=>"Halt!", -padx=>'6', -pady=>'6', -borderwidth=>'12', -command=>sub{&handler('STOP');})->pack(-side=>'left');
		$panel_1_1->Label(-text=>'   ', -borderwidth=>'4')->pack(-side=>'left', -fill=>'y');
		$panel_1_1->Button(-text=>"Langsamer", -padx=>'6', -pady=>'6', -borderwidth=>'12', -command=>sub{&handler('SLOW');})->pack(-side=>'left');

	my $panel_2 = $panel->Frame(-relief=>'flat', -borderwidth=>'4')->pack(-side=>'left', -fill=>'y');
		$panel_2->Button(-text=>"Links", -padx=>'6', -pady=>'6', -borderwidth=>'12', -command=>sub{&handler('LEFT');})->pack(-side=>'left');

	my $panel_3 = $panel->Frame(-relief=>'flat', -borderwidth=>'4')->pack(-side=>'left', -fill=>'y');

		$panel_3->Frame(-relief=>'flat', -borderwidth=>'16')->pack(-side=>'top', -fill=>'x');
		$panel_3->Button(-text=>"Vorwarts", -padx=>'6', -pady=>'6', -borderwidth=>'12', -command=>sub{&handler('FORWARD');})->pack(-side=>'top');
		$panel_3->Label(-borderwidth=>'1', -image=>'top')->pack(-side=>'top');
		$panel_3->Button(-text=>"Ruckwarts", -padx=>'6', -pady=>'6', -borderwidth=>'12', -command=>sub{&handler('BACKWARD');})->pack(-side=>'top');

	my $panel_4 = $panel->Frame(-relief=>'flat', -borderwidth=>'4')->pack(-side=>'left', -fill=>'y');
		$panel_4->Button(-text=>"Rechts", -padx=>'6', -pady=>'6', -borderwidth=>'12', -command=>sub{&handler('RIGHT');})->pack(-side=>'left');

eval {
	$cfg->load();
	&connect();
	$interrupt = Tk::After->new($main,25,'repeat',\&transmitter);
};
if( $@ ) {
	$main->messageBox(-icon=>'error',
							-message => $@,
							-title => 'Application Error',
							-type=>'OK');
	die "Panic, application error cannot be recovered\n";
}

MainLoop;
exit(0);


sub transmitter {
#	$PortObj->write($prot->getProtocolValue('CMD_CLS_MEM_0'));
	unless( $mutex->wait(0) )  { # Get write access to cache through a Lock (mutex).
		$mutex->set();
		if( defined( $transport_queue )) {
			$PortObj->transmit_char(ord($transport_queue));
			undef( $transport_queue );
		} else {
			$PortObj->transmit_char(0xAA);
		}
		$mutex->reset();
	} 
}


sub connect {
	$PortObj = new Win32::SerialPort($cfg->getValue('PORT')) || die( "Cannot open serial port " . $cfg->getValue('PORT'));    # $quiet is optional

	$PortObj->user_msg($cfg->getValue('USER_MSG'));
	$PortObj->databits($cfg->getValue('DATABITS'));
	$PortObj->baudrate($cfg->getValue('BAUDRATE'));
	$PortObj->parity($cfg->getValue('PARITY'));
	$PortObj->stopbits($cfg->getValue('STOPBITS'));
	$PortObj->handshake($cfg->getValue('HANDSHAKE'));
	$PortObj->buffers($cfg->getValue('BUFFERS'),$cfg->getValue('BUFFERS') );

	$PortObj->write_settings || undef $PortObj;

	die "Serial port " . $cfg->getValue('PORT') . " cannot be initialized correctly." unless(defined($PortObj));
}


sub handler {
	my $param = shift;

	&_handler('H') if( lc($param) eq lc('UP') );
	&_handler('h') if( lc($param) eq lc('DOWN') );
	&_handler('V') if( lc($param) eq lc('FAST') );
	&_handler('v') if( lc($param) eq lc('SLOW') );
	&_handler('s') if( lc($param) eq lc('STOP') );
	&_handler('A') if( lc($param) eq lc('LEFT') );
	&_handler('a') if( lc($param) eq lc('RIGHT') );
	&_handler('f') if( lc($param) eq lc('FORWARD') );
	&_handler('r') if( lc($param) eq lc('BACKWARD') );
}


sub _handler {
	unless( $mutex->wait(0) )  { # Get write access to cache through a Lock (mutex).
		$mutex->set();
		$transport_queue = shift;
		$mutex->reset();
	}
}

